﻿using System;
using System.Collections.Generic;
using System.Windows.Input;
using Hopscotch.Common;
using Hopscotch.Common.Contracts.EnqService;
using Hopscotch.Common.Logging;
using Hopscotch.Domain.Common;
using Hopscotch.Domain.Enquiry;
using Hopscotch.Presentation.Common;
using Hopscotch.Presentation.Common.Collections;
using Hopscotch.Presentation.Common.Data;
using Hopscotch.Presentation.Common.Events;
using Hopscotch.Presentation.Common.Threading;
using Hopscotch.Presentation.Communication.Events;
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Prism.PubSubEvents;

namespace Hopscotch.Presentation.TradeModule.ViewModels
{
    public class TradeBlotterViewModel : ViewModelBase, ITradeBlotterViewModel
    {
        private readonly ILogger logger;
        private readonly IEventAggregator eventAggregator;
        private readonly IDispatcher dispatcher;
        private readonly IShellContext workspaceContext;
        private readonly ITradeEnqClient tradeEnqClient;

        private IEntityCollection<TradeEnq, int> trades;
        private TradeEnq selectedTrade;

        private readonly Dictionary<EntityType, CheckableMenuItem> interopMenuItems;
        public ICommand RefreshQueryCommand { get; private set; }
        
        private bool isLoaded;

        public TradeBlotterViewModel()
        {
            interopMenuItems = new Dictionary<EntityType, CheckableMenuItem>();

            this.ViewTitle = "Trade Blotter";
            this.Icon16Uri = new Uri(IconPaths.Wallet16);

            interopMenuItems[EntityType.Trade] = new CheckableMenuItem() { Header = "Trade", IsChecked = true };
            interopMenuItems[EntityType.Account] = new CheckableMenuItem() { Header = "Account" };
            interopMenuItems[EntityType.Instrument] = new CheckableMenuItem() { Header = "Instrument" };
        }

        public TradeBlotterViewModel(
            IEventAggregator eventAggregator,
            IDispatcher dispatcher,
            IShellContext workspaceContext,
            ITradeEnqClient tradeEnqClient)
            : this()
        {
            this.logger = AppLogger.CreateLogger<TradeBlotterViewModel>();

            this.eventAggregator = eventAggregator;
            this.dispatcher = dispatcher;
            this.workspaceContext = workspaceContext;
            this.tradeEnqClient = tradeEnqClient;

            //Commands
            RefreshQueryCommand = new DelegateCommand(RefreshQuery);

            //Subscribe to events
            this.eventAggregator.GetEvent<ConnectionChangedEvent>().Subscribe(ConnectionChangedReceived, ThreadOption.BackgroundThread);
        }


        public Dictionary<EntityType, CheckableMenuItem> InteropMenuItems
        {
            get
            {
                return interopMenuItems;
            }
        }

        public IEntityCollection<TradeEnq, int> Trades
        {
            get
            {
                return trades;
            }
            private set
            {
                trades = value;
                RaisePropertyChanged();
            }
        }

        public TradeEnq SelectedTrade
        {
            get
            {
                return selectedTrade;
            }
            set
            {
                selectedTrade = value;
                BroadcastInterop(selectedTrade);
            }
        }

        public bool IsConnected
        {
            get { return tradeEnqClient.ConnectionState == ConnectionState.Connected; }
        }

        public ConnectionState ConnectionState
        {
            get { return tradeEnqClient.ConnectionState; }
        }

        public override void OnValidate()
        {
        }

        private bool IsBroadcastInteropEnabled()
        {
            foreach (var kvp in interopMenuItems)
            {
                if (kvp.Value.IsChecked)
                    return true;
            }
            return false;
        }

        private void BroadcastInterop(TradeEnq trade)
        {
            if (trade == null)
                return;

            if (!IsBroadcastInteropEnabled())
                return;

            var interopPayload = new InteropBroadcastPayload(workspaceContext);

            if (interopMenuItems[EntityType.Trade].IsChecked)
                interopPayload.Add(EntityType.Trade, trade.Id);

            if (interopMenuItems[EntityType.Instrument].IsChecked)
                interopPayload.Add(EntityType.Instrument, trade.InstrumentId);
            //zxzx, Refactor to make use of entity keys..

            this.eventAggregator.GetEvent<InteropBroadcastEvent>().Publish(interopPayload);
        }

        public void OnLoaded()
        {
            if (!isLoaded)
            {
                RefreshQuery();
                isLoaded = true;
            }
        }

        private void RefreshQuery()
        {
            Trades = new DispatcherCollection<TradeEnq, int>(dispatcher);
            tradeEnqClient.Subscribe("1", Trades);
        }

        private void ConnectionChangedReceived(ConnectionChangedEvent connectionChangedEvent)
        {
            if (connectionChangedEvent == null)
                return;
      
            RaisePropertyChanged(nameof(IsConnected));
            RaisePropertyChanged(nameof(ConnectionState));
        }
    }
}
